﻿namespace Cubezicles.UI
{
    using System;
    using System.Collections.Generic;
    using Microsoft.Xna.Framework;
    using Microsoft.Xna.Framework.Graphics;
    using Microsoft.Xna.Framework.Input;

    public class Control
    {
        // Icon image
        public Texture2D Texture;

        // Source rectangle for when the mouse is not hovering over this element
        public Rectangle SourceRectBlur;

        // Source rectangle for when the mouse is hovering over this element
        public Rectangle SourceRectFocus;

        // Source rectangle for when the object is "active" (determined by OnClick)
        public Rectangle? SourceRectActive = null;

        // A function that takes the width and height of the screen and returns
        // an appropriate bounding box to check for clicking
        public Func<Control, int, int, Rectangle> GetBoundBox;

        // Function to call when this element is clicked on (or nothing)
        public Action<Control> OnClick = (control) => { };

        // True iff the mouse is over this element
        public bool HasFocus { get; protected set; }

        public bool notholdbtn = false;

        // Currently-used source rectangle for the sprite sheet
        public Rectangle CurrentSourceRect
        {
            get { return HasFocus ? SourceRectFocus : SourceRectBlur; }
        }

        // Draw this icon/menu item
        public void Draw(SpriteBatch spriteBatch, Viewport viewport)
        {
            Rectangle bound = GetBoundBox(this, viewport.Width, viewport.Height);
            Rectangle src = HasFocus ? SourceRectFocus : SourceRectBlur;

            if (SourceRectActive.HasValue)
            {
                src = SourceRectActive.Value;
            }

            spriteBatch.Draw(Texture, bound, src, Color.White);
        }

        // Does this icon contain the given point?
        public bool Contains(Viewport viewport, Point msp)
        {
            return GetBoundBox(this, viewport.Width, viewport.Height).Contains(msp);
        }

        // Check if the mouse is over this icon, and if so, if the button is pressed
        public void Update(Viewport viewport, MouseState ms, MouseState oldms)
        {
            // Update HasFocus and also check in case we need to fire a click
            // delegate
            if (HasFocus = Contains(viewport, new Point(ms.X, ms.Y)))
            {
                if (ms.LeftButton == ButtonState.Pressed && (oldms.LeftButton == ButtonState.Released || notholdbtn))
                {
                    OnClick(this);
                }
            }
        }
    }

    public class UI : DrawableGameComponent
    {
        List<Control> controls;

        // Time controls
        Control pause_btn, play_btn, ff_btn, fff_btn;

        public UI(Game1 game) : base(game) { this.DrawOrder = (int)Game1.DisplayOrder.UI; }

        // Get the Game1 object stored by the base class
        private Game1 game1 { get { return (Game1)Game; } }

        protected override void LoadContent()
        {
            // Create a list of UI controls
            controls = new List<Control>();

            // Add the top bar
            var topTex = Game.Content.Load<Texture2D>("UI/topbar");
            controls.Add(new Control()
            {
                Texture = topTex,
                GetBoundBox = (c, w, h) =>
                    new Rectangle(0, 0, w, c.Texture.Height),
                SourceRectFocus = topTex.GetDefaultRectangle(),
                SourceRectBlur = topTex.GetDefaultRectangle()
            });

            // Add bottom bar
            var bottomTex = Game.Content.Load<Texture2D>("UI/bottombar");
            controls.Add(new Control()
            {
                Texture = bottomTex,
                GetBoundBox = (c, w, h) =>
                    new Rectangle(0, h - c.Texture.Height, w, c.Texture.Height),
                SourceRectFocus = bottomTex.GetDefaultRectangle(),
                SourceRectBlur = bottomTex.GetDefaultRectangle()
            });

            // Add the background graphic
            var bgTex = Game.Content.Load<Texture2D>("UI/controlbg");
            controls.Add(new Control()
            {
                Texture = bgTex,
                GetBoundBox = (c, w, h) =>
                    new Rectangle(0, h - c.Texture.Height, c.Texture.Width, c.Texture.Height),
                SourceRectFocus = bgTex.GetDefaultRectangle(),
                SourceRectBlur = bgTex.GetDefaultRectangle(),
            });

            // Load icon textures first
            Texture2D icon = Game.Content.Load<Texture2D>("UI/icon");
            Texture2D zoom = Game.Content.Load<Texture2D>("UI/zoomall");
            Texture2D time = Game.Content.Load<Texture2D>("UI/timeall");
            Texture2D cameraControls = Game.Content.Load<Texture2D>("UI/camera");

            // Add person icon
            controls.Add(new Control()
            {
                Texture = icon,
                GetBoundBox = (c, w, h) =>
                    new Rectangle(0, h - bgTex.Height + 70, 38, 54),
                // Bring up the employee manager
                //This clicking is tooooo fast. Need to calm it down some.
                OnClick = (control) =>
                {
                    bool isVisible = !game1.EmployeeManager.managerPane.IsVisible;
                    turnOffAllPanes();
                    game1.EmployeeManager.managerPane.IsVisible = isVisible;
                    if (game1.time.CurrTimeSpeed == Clock.TimeSpeed.Paused || isVisible)
                        game1.time.PauseUnpause();
                },
                SourceRectFocus = new Rectangle(40, 0, 38, 54),
                SourceRectBlur = new Rectangle(0, 0, 38, 54)
            });

            // Add coffee mug icon
            controls.Add(new Control()
            {
                Texture = icon,
                GetBoundBox = (c, w, h) =>
                    new Rectangle(0, h - bgTex.Height + 20, 38, 50),
                // Bring up the employee manager
                //This clicking is tooooo fast. Need to calm it down some.
                OnClick = (control) =>
                {
                    bool isVisible = !game1.ItemManager.managerPane.IsVisible;
                    turnOffAllPanes();
                    game1.ItemManager.managerPane.IsVisible = isVisible;
                    if (game1.time.CurrTimeSpeed == Clock.TimeSpeed.Paused || isVisible)
                        game1.time.PauseUnpause();
                },
                SourceRectFocus = new Rectangle(40, 60, 38, 50),
                SourceRectBlur = new Rectangle(0, 60, 38, 50)
            });

            // Camera zoom-in button
            controls.Add(new Control()
            {
                Texture = cameraControls,
                GetBoundBox = (c, w, h) => new Rectangle(53, h - 80, 29, 40),

                // Zoom in on click
                OnClick = (control) =>
                {
                    game1.CurrentCam.zoomIn();
                },
                notholdbtn = true,
                SourceRectFocus = new Rectangle(60, 53, 29, 40),
                SourceRectBlur = new Rectangle(60, 0, 29, 40)
            });

            // Add camera zoom-out button
            controls.Add(new Control()
            {
                Texture = cameraControls,
                GetBoundBox = (c, w, h) => new Rectangle(53, h - 40, 30, 54),

                // Zoom out on click
                OnClick = (control) =>
                {
                    game1.CurrentCam.zoomOut();
                },
                notholdbtn = true,
                SourceRectFocus = new Rectangle(89, 53, 30, 54),
                SourceRectBlur = new Rectangle(89, 0, 30, 54),
            });

            // Add clockwise-rotation button
            controls.Add(new Control()
            {
                Texture = cameraControls,
                GetBoundBox = (c, w, h) => new Rectangle(20, h - 60, 30, 50),

                // Rotate camera clockwise
                OnClick = (control) =>
                {
                    game1.CurrentCam.rotateClock();
                },
                notholdbtn = true,
                SourceRectFocus = new Rectangle(0, 53, 30, 50),
                SourceRectBlur = new Rectangle(0, 0, 30, 50)
            });

            // Add counterclockwise-rotation button
            controls.Add(new Control()
            {
                Texture = cameraControls,
                GetBoundBox = (c, w, h) => new Rectangle(85, h - 60, 27, 50),

                // Rotate camera counterclockwise
                OnClick = (control) =>
                {
                    game1.CurrentCam.rotateCounter();
                },
                notholdbtn = true,
                SourceRectFocus = new Rectangle(30, 53, 27, 50),
                SourceRectBlur = new Rectangle(30, 0, 28, 50)
            });

            int x = 160;
            // Add pause button
            pause_btn = new Control()
            {
                Texture = time,
                GetBoundBox = (c, w, h) => new Rectangle(x, 3, 25, 25),

                // Set game speed to "pause" and mark this icon active
                OnClick = (control) =>
                {
                    game1.time.CurrTimeSpeed = Clock.TimeSpeed.Paused;
                    controls.ForEach(c => c.SourceRectActive = null);
                },
                SourceRectFocus = new Rectangle(0, 24, 25, 25),
                SourceRectBlur = new Rectangle(0, 0, 25, 25)
            };
            controls.Add(pause_btn);

            // Add Play button
            play_btn = new Control()
            {
                Texture = time,
                GetBoundBox = (c, w, h) =>
                    new Rectangle(x + c.SourceRectBlur.X, 3, 20, 25),

                // Set game speed to "play" and mark this icon active
                OnClick = (control) =>
                {
                    game1.time.CurrTimeSpeed = Clock.TimeSpeed.SpeedPlay;
                    controls.ForEach(c => c.SourceRectActive = null);
                },
                SourceRectFocus = new Rectangle(25, 24, 20, 25),
                SourceRectBlur = new Rectangle(25, 0, 20, 25),

                // Play button is "active" by default
                SourceRectActive = new Rectangle(25, 24 * 2, 20, 25)
            };
            controls.Add(play_btn);

            // Add Fast-Forward button
            ff_btn = new Control()
            {
                Texture = time,
                GetBoundBox = (c, w, h) =>
                    new Rectangle(x + c.CurrentSourceRect.X, 3, 25, 25),

                // Set game speed to FF and mark this icon as "active"
                OnClick = (control) =>
                {
                    game1.time.CurrTimeSpeed = Clock.TimeSpeed.SpeedFF;
                    controls.ForEach(c => c.SourceRectActive = null);
                },
                SourceRectFocus = new Rectangle(45, 24, 25, 25),
                SourceRectBlur = new Rectangle(45, 0, 25, 25)
            };
            controls.Add(ff_btn);

            // Add Fast-Fast-Forward button
            fff_btn = new Control()
            {
                Texture = time,
                GetBoundBox = (c, w, h) =>
                    new Rectangle(x + c.CurrentSourceRect.X, 3, 40, 25),

                // Set game speed to FFF and mark this icon as "active"
                OnClick = (control) =>
                {
                    game1.time.CurrTimeSpeed = Clock.TimeSpeed.SpeedFFF;
                    controls.ForEach(c => c.SourceRectActive = null);
                },

                SourceRectFocus = new Rectangle(70, 24, 40, 25),
                SourceRectBlur = new Rectangle(70, 0, 40, 25)
            };
            controls.Add(fff_btn);
            
            Texture2D helptex = Game.Content.Load<Texture2D>("UI/help");

            // Add person icon
            controls.Add(new Control()
            {
                Texture = helptex,
                GetBoundBox = (c, w, h) =>
                    new Rectangle(-7, h - (helptex.Height/2), helptex.Width, helptex.Height/2),
                // Bring up the employee manager
                //This clicking is tooooo fast. Need to calm it down some.
                OnClick = (control) =>
                {
                    //Open the help pane
                    bool isVisible = !game1.HelpPane.IsVisible;
                    turnOffAllPanes();
                    game1.HelpPane.IsVisible = isVisible;
                    if (game1.time.CurrTimeSpeed == Clock.TimeSpeed.Paused || isVisible) 
                        game1.time.PauseUnpause();
                },
                SourceRectFocus = new Rectangle(0, 27, helptex.Width, helptex.Height / 2),
                SourceRectBlur = new Rectangle(0, 0, helptex.Width, helptex.Height / 2)
            });
            base.LoadContent();
        }

        public void turnOffAllPanes()
        {
            game1.ItemManager.managerPane.IsVisible = false;
            game1.EmployeeManager.managerPane.IsVisible = false;
            game1.HelpPane.IsVisible = false;

        }

        public override void Update(GameTime gameTime)
        {
            game1.UIClicked = false;


            // Not sure if this is right! ***********
            int x = game1.ms.X;
            int y = game1.ms.Y;
            // check if the click was inside one of the manager panes ------//
            if (game1.EmployeeManager.managerPane.IsInsidePane(x, y) ||
                game1.EmployeeManager.newHireManagerPane.IsInsidePane(x,y) ||
                game1.ItemManager.managerPane.IsInsidePane(x, y) ||
                game1.MoneyManager.managerPane.IsInsidePane(x, y))
                game1.UIClicked = true;

            // MouseState ms = Mouse.GetState();
            controls.ForEach(control =>
            {
                control.Update(GraphicsDevice.Viewport, game1.ms, game1.oldms);
                if (control.HasFocus)
                {
                    game1.UIClicked = true;
                }
            });

            switch (game1.time.CurrTimeSpeed)
            {
                //Update the active time control based on which time speed's active
                case Clock.TimeSpeed.SpeedFFF:
                    pause_btn.SourceRectActive = null;
                    play_btn.SourceRectActive = null;
                    ff_btn.SourceRectActive = null;
                    fff_btn.SourceRectActive = new Rectangle(70, 48, 40, 25);
                    break;
                case Clock.TimeSpeed.SpeedFF:
                    pause_btn.SourceRectActive = null;
                    play_btn.SourceRectActive = null;
                    ff_btn.SourceRectActive = new Rectangle(45, 48, 25, 25);
                    fff_btn.SourceRectActive = null;
                    break;
                case Clock.TimeSpeed.SpeedPlay:
                    pause_btn.SourceRectActive = null;
                    play_btn.SourceRectActive = new Rectangle(25, 48, 20, 25);
                    ff_btn.SourceRectActive = null;
                    fff_btn.SourceRectActive = null;
                    break;
                default:
                    pause_btn.SourceRectActive = new Rectangle(0, 48, 25, 25);
                    play_btn.SourceRectActive = null;
                    ff_btn.SourceRectActive = null;
                    fff_btn.SourceRectActive = null;
                    break;
            }
        }

        public override void Draw(GameTime gameTime)
        {
            game1.SpriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend);
            controls.ForEach(control =>
                control.Draw(game1.SpriteBatch, GraphicsDevice.Viewport));
            game1.SpriteBatch.End();

            base.Draw(gameTime);
        }
    }
}
